<template>
    <div class="caih-tags" v-if="settings.tagsView">
        <el-icon class="btn" :class="{ disabled: state.disabledPrev }" @click="handleScroll({ deltaY: -1 } as any)">
            <el-icon-arrow-left />
        </el-icon>
        <div
            class="tags"
            ref="scrollbarRef"
            @mousewheel="handleScroll"
            @scroll="(e:any) => (state.scrollLeft = e.target.scrollLeft)"
        >
            <div class="content" ref="tagsContentRef">
                <router-link
                    v-for="tag in tags.viewTags"
                    :key="tag.fullPath"
                    :to="tag.fullPath"
                    @contextmenu.prevent="handleShowMenu($event, tag)"
                >
                    {{ tag.title }}
                    <el-icon v-if="!tag.affix" @click.stop.prevent="tags.closeViewTag(tag)"><el-icon-close /></el-icon>
                </router-link>
            </div>
        </div>
        <el-icon class="btn" :class="{ disabled: state.disabledNext }" @click="handleScroll({ deltaY: 1 } as any)">
            <el-icon-arrow-right />
        </el-icon>
        <el-icon class="btn close" @click="tags.batchClose(TagsActions.CLOSE_ALL)"><el-icon-close /></el-icon>
        <ul
            ref="menuRef"
            class="menu"
            v-show="state.visible"
            :style="{ left: `${state.left}px`, top: `${state.top}px` }"
        >
            <li @click="handleMenuAction(TagsActions.REFRESH)">刷新</li>
            <li class="split"></li>
            <li @click="handleMenuAction(TagsActions.CLOSE)">关闭标签</li>
            <li @click="handleMenuAction(TagsActions.CLOSE_OTHER)">关闭其他</li>
            <li @click="handleMenuAction(TagsActions.CLOSE_RIGHT)">关闭右侧</li>
            <li @click="handleMenuAction(TagsActions.CLOSE_ALL)">全部关闭</li>
        </ul>
    </div>
</template>

<script setup lang="ts">
import { onMounted, onUnmounted, reactive, ref, watch } from "vue";
import { useTagsStore, TagsActions, type ViewTag } from "@/stores/tags";
import { useSettingsStore } from "@/stores/settings";
import waiting from "@/utils/waiting";

type State = {
    visible: boolean;
    left: number;
    top: number;
    selected: ViewTag | null;
    scrollLeft: number;
    disabledPrev: boolean;
    disabledNext: boolean;
};

const state = reactive<State>({
    visible: false,
    left: 0,
    top: 0,
    selected: null,
    scrollLeft: 0,
    disabledPrev: true,
    disabledNext: true,
});
const menuRef = ref<HTMLDivElement>();
const tagsContentRef = ref<HTMLDivElement>();
const scrollbarRef = ref<HTMLDivElement>();
const tags = useTagsStore();
const settings = useSettingsStore();

const calcBtnStatus = async () => {
    if (!scrollbarRef.value) return;
    await waiting(100);

    const { scrollLeft, scrollWidth, clientWidth } = scrollbarRef.value;

    state.disabledPrev = scrollLeft <= 0;
    state.disabledNext = scrollWidth === clientWidth || scrollLeft + clientWidth >= scrollWidth;
};

const handleScroll = (e: WheelEvent) => {
    const left = scrollbarRef.value!.scrollLeft - 100 * (e.deltaY > 0 ? -1 : 1);

    scrollbarRef.value!.scrollTo({
        behavior: "smooth",
        left,
    });

    calcBtnStatus();
};

const handleShowMenu = (e: MouseEvent, tag: ViewTag) => {
    state.selected = tag;

    state.left = e.clientX;
    state.top = e.clientY;
    state.visible = true;
};

const handleCloseMenu = () => {
    state.visible = false;
    state.selected = null;
};

const handleCloseMenuFromDocument = (e: MouseEvent) => {
    if (e.target && menuRef.value!.contains(e.target as HTMLDivElement)) return;
    handleCloseMenu();
};

const handleMenuAction = (action: TagsActions) => {
    switch (action) {
        case TagsActions.REFRESH:
            tags.refreshView(state.selected!);
            break;
        case TagsActions.CLOSE:
            tags.closeViewTag(state.selected!);
            break;
        default:
            tags.batchClose(action, state.selected);
    }
    handleCloseMenu();
};

watch(
    () => state.visible,
    (visible) => {
        if (visible) {
            document.addEventListener("click", handleCloseMenuFromDocument);
        } else {
            document.removeEventListener("click", handleCloseMenuFromDocument);
        }
    },
);

watch(
    () => tags.viewTags.length,
    () => calcBtnStatus(),
);

onMounted(() => {
    window.addEventListener("resize", calcBtnStatus);
});
onUnmounted(() => {
    window.removeEventListener("resize", calcBtnStatus);
});
</script>

<style lang="scss" scoped>
.caih-tags {
    --tags-height: 40px;

    flex: none;
    display: flex;
    align-items: center;
    background: #fff;
    box-shadow: 0px -1px 0px 0px rgba(0, 0, 0, 0.1) inset;
    padding: 8px 20px 0;
    .btn {
        width: 16px;
        height: 16px;
        color: #000;
        border: 1px solid #000;
        cursor: pointer;
        &.close {
            margin-left: 8px;
        }
        &.disabled {
            color: rgba(#000, 0.15);
            border-color: rgba(#000, 0.15);
        }
    }
    .tags {
        flex: 1;
        height: var(--tags-height);
        overflow: hidden;
        margin: 0 12px;
        .content {
            display: flex;
            gap: 2px;
            a {
                flex: none;
                display: flex;
                align-items: center;
                gap: 8px;
                height: var(--tags-height);
                color: rgba(#000, 0.65);
                border: 1px solid rgba(#000, 0.15);
                border-bottom: none;
                border-radius: 4px 4px 0px 0px;
                padding: 0 16px;
                box-sizing: border-box;
                &.router-link-active {
                    color: var(--el-color-primary);
                }
                .el-icon {
                    color: #979797;
                }
            }
        }
    }
    .menu {
        width: 100px;
        background: var(--el-bg-color);
        box-shadow: 0 0 6px 0 var(--el-border-color);
        padding: 10px 15px;
        position: absolute;
        z-index: 1000;
        li {
            line-height: 30px;
            cursor: pointer;
            &.split {
                border-bottom: 1px solid var(--el-border-color);
                margin: 5px 0;
                cursor: unset;
            }
            &.disabled {
                color: #c0c4cc;
                cursor: not-allowed;
            }
        }
    }
}
</style>
